import { useEffect, useRef, useState } from "react";
import { renderToString } from "react-dom/server";
import { View, LineLayer } from "mapvgl";
import WindowInfo from "components/WindowInfo";
import Loader from "components/Loader";
import DetailsModal from "components/DetailsModal";
import Player from "components/Player";
import carIcon from "assets/imgs/carIcon.png";
import { getCarLine } from "api/carLine";
const line = require("assets/lines.json");
const byRegion = require("assets/baiyun.json");

export default function Map3D() {
  const BMapGL = window.BMapGL;
  const BMapGLLib = window.BMapGLLib;
  const timerRef = useRef(null); // 轮播定时器
  const BMAP_INSTANCE = useRef(null); //实例
  const VIEW_INSTANCE = useRef(null); // mapVgl视图实例
  const LUSHU_INSTANCE = useRef(null); // 路书实例
  let currentRegionIndex = useRef(-1); // 轮播下标
  const [isLoaded, setIsLoaded] = useState(false); // 加载状态
  const [isModalOpen, setIsShowModal] = useState(false); // 模态框控制
  const [isShowPlayer, setIsShowPlayer] = useState(false); // 播放器控制

  useEffect(() => {
    console.log("———useEffect执行次数———");
    // 1. 创建地图实例
    initMap();

    let { current: map } = BMAP_INSTANCE;
    // 地图加载完毕回调
    map.addEventListener("tilesloaded", () => {
      // 更改加载状态
      setIsLoaded(true);
    });

    // 2. 创建MapVGL图层管理器
    VIEW_INSTANCE.current = new View({
      map,
    });

    // 3. 创建蝌蚪线图 可视化图层
    let lineLayer = new LineLayer({
      color: "#1892ff",
      width: 1,
      animation: true,
      duration: 25, // 循环时间
      trailLength: 1.6, // 拖尾长度占间隔的0.4
      interval: 0.5, // 粒子长度占线整体长度的0.2
    });

    // 4. 准备好规范化坐标数据
    let lineData = line.geometries.map((item) => {
      return {
        geometry: {
          ...item,
        },
      };
    });

    // 5. 关联图层与数据，享受震撼的可视化效果
    lineLayer.setData(lineData);
    VIEW_INSTANCE.current.addLayer(lineLayer);

    setBoundary(); // 广州区域镂空
    mapActive(); // 开启轮播

    setTimeout(() => {
      map.setTilt(36);
      map.setZoom(12.5);
    }, 4000);
  }, []);

  /**
   * 初始化地图
   */
  const initMap = () => {
    BMAP_INSTANCE.current = new BMapGL.Map("map_container", {
      minZoom: 12,
      maxZoom: 17,
    });
    let point = new BMapGL.Point(113.330476, 23.284015);
    BMAP_INSTANCE.current.centerAndZoom(point, 12);
    BMAP_INSTANCE.current.enableScrollWheelZoom(true);
    BMAP_INSTANCE.current.setMapStyleV2({
      styleId: "9df0a502c676f3c9bfaff44a5820303e",
    });
  };

  /**
   * 设置区域镂空效果
   */
  const setBoundary = () => {
    const Boundary = new BMapGL.Boundary();
    Boundary.get("广州市白云区", function (rs) {
      let boundary = new BMapGL.Polygon(rs.boundaries, {
        fillOpacity: 0,
        strokeWeight: 3,
        strokeColor: "#ddd",
      });
      BMAP_INSTANCE.current.addOverlay(boundary);
    });
  };

  /**
   * 轮播 开启定时器 进行高亮显示
   * @param {*} time 定时器时间
   */
  const mapActive = (time = 4000) => {
    timerRef.current = setInterval(() => {
      // 取消高亮 清除所有覆盖物除外层区域边界
      BMAP_INSTANCE.current.getOverlays().forEach((element, index) => {
        if (index) {
          BMAP_INSTANCE.current.removeOverlay(element);
        }
      });
      currentRegionIndex.current++;

      // 高亮展示
      createByRegion(currentRegionIndex.current);
      createCustomOverlay(currentRegionIndex.current);

      if (currentRegionIndex.current >= 23) {
        currentRegionIndex.current = -1;
      }
    }, time);
  };

  /**
   * 高亮当前区域
   */
  const createByRegion = () => {
    let region = new BMapGL.GeoJSONLayer("by-child", {
      reference: "GCJ02",
      dataSource: byRegion.features[currentRegionIndex.current],
      polygonStyle: function () {
        return {
          fillColor: "#193151",
          strokeColor: "#fff",
          strokeWeight: 2,
          strokeOpacity: 1,
          fillOpacity: 1,
          strokeStyle: "dashed",
        };
      },
    });
    BMAP_INSTANCE.current.addGeoJSONLayer(region);
  };

  /**
   * 高亮自定义覆盖物
   */
  const createCustomOverlay = () => {
    const cityGeo = new BMapGL.Geocoder();
    let {
      properties: { name: regionName },
    } = byRegion.features[currentRegionIndex.current];
    cityGeo.getPoint(
      regionName,
      (point) => {
        let pt = new BMapGL.Point(point.lng, point.lat);
        // 添加自定义覆盖物
        BMAP_INSTANCE.current.addOverlay(new RadarOverlay(pt, regionName));
      },
      "广州市"
    );
  };

  /**
   * 自定义覆盖物
   * @param {*} point 位置信息
   * @param {*} regionName 区域名字
   */
  class RadarOverlay extends BMapGL.Overlay {
    constructor(point, regionName) {
      super();
      this.point = point;
      this.regionName = regionName;
    }

    initialize(map) {
      this._map = map;
      let template = renderToString(
        <WindowInfo regionName={this.regionName} />
      );
      let divFragment = document
        .createRange()
        .createContextualFragment(template);
      let div = divFragment.getElementById("windowInfo");
      // 卡片整体鼠标移入移出效果
      div.addEventListener("mouseenter", this.handleMouseenter.bind(this));
      div.addEventListener("mouseleave", this.handleMouseout.bind(this));
      // 卡片详情点击效果
      let btn = divFragment.getElementById("detailbtn");
      btn.addEventListener("click", this.handleClick.bind(this));
      map.getPanes().markerPane.appendChild(div);
      this._div = div;
      return div;
    }

    draw() {
      // 根据地理坐标转换为像素坐标，并设置给容器
      let position = this._map.pointToOverlayPixel(this.point);
      this._div.style.left = `${position.x - 100}px`;
      this._div.style.top = `${position.y - 30}px`;
    }

    handleMouseenter() {
      // 鼠标移入 清除定时器 阻止轮播 设置类名改变展示内容
      clearInterval(timerRef.current);
      this._div.setAttribute("class", "selected");
    }

    handleMouseout() {
      // 鼠标移出 开启定时器 开启轮播 隐藏展示全部内容
      mapActive();
      this._div.setAttribute("class", "");
    }

    handleClick() {
      // 详情 打开模态框
      setIsShowModal(true);
    }
  }

  /**
   * 移除图层 开启运行轨迹
   */
  const OpenTravel = () => {
    // 关闭模态框 展示播放器
    setIsShowModal(false);
    setIsShowPlayer(true);
    // 停止轮播
    clearInterval(timerRef.current);
    // 移除所有图层
    BMAP_INSTANCE.current.getOverlays().forEach((element, index) => {
      if (index) {
        BMAP_INSTANCE.current.removeOverlay(element);
      }
    });

    // 获取保存之前的飞线图层 轨迹动画关闭再打开
    // let flyLayer = VIEW_INSTANCE.current.getAllLayers()[0];
    // 删除蝌蚪飞线图层
    // VIEW_INSTANCE.current.removeAllLayers();
    // 绘制路书
    initTravel();
  };

  /**
   * 设置产生运行轨迹
   */
  const initTravel = async () => {
    let { current: map } = BMAP_INSTANCE;
    let resArr = await getCarLine({
      equipmentNo: "90288400010",
      startTime: "2020-02-22",
      endTime: "2023-02-22",
    });
    // 转换坐标
    let pointArr = [];
    resArr.forEach((element) => {
      pointArr.push(new BMapGL.Point(element.longitude, element.latitude));
    });
    let polyLineOverLine = new BMapGL.Polyline(pointArr, {
      strokeColor: "red",
    });
    // 添加视图
    map.addOverlay(polyLineOverLine);
    // 调整视图设置视图最佳位置
    map.setViewport(pointArr);
    LUSHU_INSTANCE.current = new BMapGLLib.LuShu(map, pointArr, {
      defaultContent: "出发啦", // "信息窗口文案"
      autoView: true, // 是否开启自动视野调整，如果开启那么路书在运动过程中会根据视野自动调整
      speed: 300,
      icon: new BMapGL.Icon(carIcon, new BMapGL.Size(30, 30)),
    });
  };

  // 关闭模态框
  const closeModal = () => {
    setIsShowModal(false);
  };

  /**
   * 关闭播放器 开启轮播 调整地图位置
   */
  const closePlayer = () => {
    setIsShowPlayer(false);
    mapActive();
    BMAP_INSTANCE.current.setTilt(36);
    BMAP_INSTANCE.current.setZoom(12.5);
  };

  console.log("————组件渲染次数————");

  const test = () => {
    console.log("测试按钮");
  };

  return (
    <>
      {!isLoaded ? <Loader /> : null}
      <div
        style={{
          height: "100%",
          width: "100%",
          position: "absolute",
        }}
        id="map_container"
      ></div>
      <button
        onClick={test}
        style={{ position: "absolute", zIndex: 99999, background: "red" }}
      >
        test
      </button>
      {isModalOpen ? (
        <DetailsModal
          isModalOpen={isModalOpen}
          closeModal={closeModal}
          OpenTravel={OpenTravel}
        />
      ) : null}
      {isShowPlayer ? (
        <Player LUSHU_INSTANCE={LUSHU_INSTANCE} closePlayer={closePlayer} />
      ) : null}
    </>
  );
}
